/*
 * Copyright © 2004-2014 chenYuan. All rights reserved.
 * @Website:wwww.jspx.net
 * @Mail:39793751@qq.com
 * @author: chenYuan , 陈原
 * @License: Jspx.net Framework Code is open source (LGPL)，Jspx.net Framework 使用LGPL 开源授权协议发布。
 * @jvm:jdk1.6+  x86/amd64
 *
 */
package com.jspx.txweb.result;

import com.jspx.boot.EnvFactory;
import com.jspx.boot.environment.Environment;
import com.jspx.boot.environment.EnvironmentTemplate;
import com.jspx.boot.environment.Placeholder;
import com.jspx.json.JSONException;
import com.jspx.json.JSONObject;
import com.jspx.txweb.Action;
import com.jspx.txweb.ActionInvocation;
import com.jspx.txweb.Result;
import com.jspx.txweb.annotation.Redirect;
import com.jspx.txweb.config.ResultConfigBean;
import com.jspx.txweb.support.ActionSupport;
import com.jspx.txweb.util.RequestMap;
import com.jspx.txweb.util.RequestUtil;
import com.jspx.txweb.util.SessionMap;
import com.jspx.txweb.util.TXWebUtil;
import com.jspx.utils.BeanUtil;
import com.jspx.utils.ClassUtil;
import com.jspx.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;


/**
 * Created by IntelliJ IDEA.
 * User:chenYuan (mail:39793751@qq.com)
 * Date: 2006-12-27
 * Time: 9:16:23
 */
public abstract class ResultSupport implements Result {
    final static protected EnvironmentTemplate envTemplate = EnvFactory.getEnvironmentTemplate();
    final static private Logger log = LoggerFactory.getLogger(ResultSupport.class.getName());
    final static protected boolean debug = envTemplate.getBoolean(Environment.logJspxDebug);
    //json 无对应返回标识
    private static final String KEY_result = "result";
    private static final String KEY_grid = "grid";
    static final String KEY_RocFormatXML = "xml"; //xml 需要设置 json 为默认
    private static final String[] gridMethods = new String[]{"currentPage", "count", "totalCount", "sort", "list"};

    public ResultSupport() {

    }

    private ResultConfigBean resultConfig = null;

    public ResultConfigBean getResultConfig() {
        return resultConfig;
    }

    public void setResultConfig(ResultConfigBean resultConfig) {
        this.resultConfig = resultConfig;
    }


    /**
     * 得到配置的跳转路径
     *
     * @param actionInvocation 得到配置的地址
     * @return 返回响应对应的地址
     * 解析错误
     */
    String getConfigLocationUrl(ActionInvocation actionInvocation) {
        Action action = actionInvocation.getActionProxy().getAction();
        ResultConfigBean resultConfigBean = getResultConfig();
        if (resultConfigBean == null) return StringUtil.empty;
        String location = resultConfigBean.getValue();

        //设置变量在 KEY_RedirectUrl 中，将以这个变量为准
        if (StringUtil.isNULL(location)) {
            location = action.getEnv(ActionSupport.KEY_RedirectUrl);
        }

        //注释方式
        if (StringUtil.isNULL(location)) {
            Redirect redirect = action.getClass().getAnnotation(Redirect.class);
            if (redirect!=null&&!StringUtil.isNULL(redirect.location()))
                location = redirect.location();
        }

        if (StringUtil.isNULL(location)) return "/";
        if (location.contains("${")&&location.contains("}")) {
            EnvironmentTemplate envTemplate = EnvFactory.getEnvironmentTemplate();
            Map<String, Object> valueMap = new HashMap<String, Object>(envTemplate.getVariableMap());
            valueMap.putAll(action.getEnv());
            valueMap.put("action", action);
            Placeholder placeholder = EnvFactory.getPlaceholder();
            try {
                location = placeholder.processTemplate(valueMap, location);
            } catch (Exception e) {
                e.printStackTrace();
                return StringUtil.empty;
            }
        }
        return location;
    }
    //-----------------------------------------------------------------------------------------------------------

    /**
     * 解析得到ROC要返回的数据,这里是快捷的url参数方式
     *
     * @param actionInvocation ActionInvocation
     * @return  JSONObject
     */
   static JSONObject getRocAutoResult(ActionInvocation actionInvocation) {
        ActionSupport action = actionInvocation.getActionProxy().getAction();
        String resultMethods = action.getEnv(ActionSupport.Key_ResultMethods);
        if (StringUtil.isNULL(resultMethods)) resultMethods = action.getString(ActionSupport.Key_ResultMethods);

        JSONObject json = new JSONObject();
        if (KEY_grid.equalsIgnoreCase(resultMethods)) {
            //默认的表格调用方式
            for (String callMethod : gridMethods) {
                if (StringUtil.isNULL(callMethod)) continue;
                if (ClassUtil.isDeclaredMethod(action.getClass(), ClassUtil.methodName_get + StringUtil.capitalize(callMethod)))
                    try {
                        json.put(callMethod, BeanUtil.getProperty(action, callMethod));
                    } catch (NoSuchMethodException e) {
                        json = TXWebUtil.createRocErrorInfo(actionInvocation.getActionName(), -320010, "Invalid roc method " + callMethod + " error.调用method " + callMethod + "方法发生错误");
                        log.error(action + " Invalid method error " + callMethod, e);
                        break;
                    }
            }
        } else if (!StringUtil.isNULL(resultMethods)) {
            //简单的URL直接调用
            String[] methods = StringUtil.split(resultMethods, StringUtil.SEMICOLON);
            for (String cMethod : methods) {
                if (ClassUtil.isDeclaredMethod(action.getClass(), ClassUtil.methodName_get + StringUtil.capitalize(cMethod)))
                    try {
                        json.put(cMethod, BeanUtil.getProperty(action, cMethod));
                    } catch (NoSuchMethodException e) {
                        json = TXWebUtil.createRocErrorInfo(actionInvocation.getActionName(), -320011, "resultMethods Invalid roc method " + cMethod + " error.调用method " + cMethod + "方法发生错误");
                        log.error(action + "resultMethods Invalid method error " + cMethod, e);
                    }
            }
        } else if (action.containsKey(ActionSupport.Key_ActionResultObject)) {
            //程序设置后指定返回，roc 配置的返回会在这里返回
            Object methodResult = action.getResult();
            if (methodResult == null) {
                json.put(KEY_result, new JSONObject());
            } else if (action.getResult() instanceof JSONObject) {
                json = (JSONObject) action.getResult();
            } else if (ClassUtil.isStandardProperty(methodResult.getClass())|| BeanUtil.isArraySet(methodResult)) {
                json.put(KEY_result, methodResult);
            }  else
                json.put(KEY_result, new JSONObject(methodResult,true));
        } else {
            //找不到返回的数据，就返回提示信息
            try {
                json = action.getRocResult();
            } catch (JSONException e) {
                json = TXWebUtil.createRocErrorInfo(actionInvocation.getActionName(), -320011, "resultMethods Invalid roc method rocResult error.调用method rocResult 方法发生错误");
                log.error(action + "resultMethods Invalid method error rocResult", e);

            }
        }
        return json;
    }


    /**
     * 载入环境变量
     * @param action  action
     * @param valueMap  环境变量
     */
    static void  initPageEnvironment(ActionSupport action,Map<String, Object> valueMap)
    {
        valueMap.put(ActionSupport.Key_Request, new RequestMap(action.getRequest()));
        valueMap.put(ActionSupport.Key_Response, RequestUtil.getResponseMap(action.getResponse()));
        valueMap.put(ActionSupport.Key_Session, new SessionMap(action.getSession()));
        valueMap.put(ActionSupport.Key_Config, action.getConfig());
        valueMap.put(ActionSupport.Key_Language, action.getLanguage());
        valueMap.put(ActionSupport.Key_Option, action.getOption());
        valueMap.put(ActionSupport.Key_This, action);
    }


    /**
     *  判断是否让浏览器保持缓存
     * @param action action
     * @param response  请求
     */
    static void  checkCache(ActionSupport action,HttpServletResponse response)
    {
        String browserCache = action.getEnv(ActionSupport.BrowserCache);
        if (!StringUtil.isNULL(browserCache) && !StringUtil.toBoolean(browserCache)) {
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache,must-revalidate");
            response.setDateHeader("Expires", 0);
        }
    }

}